﻿//////////////////////////////////////////////////////////////////////////////
//
//  Copyright © 1998-2024 Glodon Company Limited.  All rights reserved.
//
//  Use of this software is subject to the terms of the Glodon license
//  agreement provided at the time of installation or download, or which
//  otherwise accompanies this software in either electronic or hard copy form.  
//
//////////////////////////////////////////////////////////////////////////////


#pragma once
#include "GnufBase.h"
#include "GnufItemDeclaration.h"

namespace gnuf {
    class Toolbar;
    class Block;
    class ButtonEx;
    class DropDownButton;
    class Module;
    class Item;

    enum class EnComponentName
    {
        eUnKnown = -1,
        eMainToolbar,
        eMainTitlebar,
        eBottomToolbar
    };


    /// \brief Ui界面构造工具路
    /// \details 用来动态的添加button和block。
    class GNUF_BASE_EXPORT UIConstructUtils
    {
    public:

        /// \brief 向一个toolbar上添加一个block，可以指定workspace的key
        /// \param cptName [in]枚举值，component的名称
        /// \param workSpace [in]workspace的key
        /// \return 返回添加的block
        static Block* addBlock(EnComponentName cptName, const std::wstring& workSpace = L"", Module* pModule = nullptr /*actived*/);

        /// \brief 插入一个block
        /// \param cptName  [in]插入的界面位置
        /// \param blockIndex   [in]插入的索引位置
        /// \param workSpace    [in]workspace的key
        /// \return 返回新增的block指针
        static Block* insertBlock(EnComponentName cptName, int blockIndex, const std::wstring& workSpace = L"", Module* pModule = nullptr /*actived*/);

        /// \brief 在特定的block添加一个button
        /// \param cmdId [in] button上需要绑定的命令
        /// \param toolbarName [in]界面位置
        /// \param block [in]block的索引值，若索引无效将会新建block并添加一个button进去，无效索引(索引小于0或者超出当前block的总数）
        /// \param type [in] 要添加的button的类型，默认为PushButton
        /// \return 返回新增的button指针
        static ButtonEx* addButton(const std::wstring& cmdId, EnComponentName toolbarName, int block, gnuf::EItemType type = EItemType::ePushButton, Module* pModule = nullptr /*actived*/);

        /// \brief 在特定位置添加一个button
        /// \param cmdId    [in]button上需要绑定的命令
        /// \param toolbarName [in]界面上的位置
        /// \param block    [in]block的索引
        /// \param buttonIndex  [in]button的索引，新的button将会插入到这个button之前
        /// \param type [in] 要添加的button的类型，默认为PushButton
        /// \return 返回新增的button指针
        static ButtonEx* insertButton(const std::wstring& cmdId, EnComponentName toolbarName, int block, int buttonIndex, gnuf::EItemType type = EItemType::ePushButton, Module* pModule = nullptr /*actived*/);

        /// \brief 删除界面toolbar上的一个命令按钮，注意！如果有多个button绑定了同一个命令，只会删除找到的第一个
        /// \param cmdId [in]要删除的命令上绑定的id
        /// \param toolbarName [in]命令按钮所处的位置
        /// \return 成功返回true，失败返回false，没有该命令同样返回false
        static bool removeButton(const std::wstring& cmdId, EnComponentName toolbarName, Module* pModule = nullptr /*actived*/);

        /// \brief 删除界面上一个block，注意！该block内的所有内容都将被清空，
        /// \param toolbarName  [in]要删除的block的位置
        /// \param pBlock   [in]block的指针
        /// \return 成功返回true
        static bool removeBlock(EnComponentName toolbarName, Block* pBlock, Module* pModule = nullptr /*actived*/);

        /// \brief 找到一个button的block和在block中的index
        /// \param cmdId    [in]绑定在这个button上的命令id
        /// \param toolbarName  [in]界面上的位置
        /// \param blockIndex   [out]block的索引值
        /// \param buttonIndex  [out]button在block中的索引值
        /// \return 找到返回button的指针，没找到返回nullptr
        static gnuf::Item* findButton(const std::wstring& cmdId, EnComponentName toolbarName, int& blockIndex, int& buttonIndex, Module* pModule = nullptr /*actived*/);

        /// \brief 定位一个block的位置
        /// \param pBlock   [in]block的指针
        /// \param toolbarName  [in]界面上位置
        /// \param blockIndex   [out]在该toolbar上的索引
        /// \return 成功返回true
        static bool findBlock(const Block* pBlock, EnComponentName toolbarName, int& blockIndex, Module* pModule = nullptr /*actived*/);


        /// \brief 连接ButtonDefinition和Button
        /// \param cmdId  连接的cmdId，用来查找defintion
        /// \param button button对象
        /// \return 连接成功返回true，连接失败返回false（通过key找不到definition）
        static bool connectToolDefinitionUseKey(const std::wstring& cmdId, ButtonEx* button, Module* pModule = nullptr /*actived*/);

        // 关于向DropDownButton中添加PushButton
        // 1.调用该类的addButton()方法，然后调用addPushButtonToDropDown()通过对应的button的key来添加
        // 2.调用addButton()方法后，用户自行通过ButtonEx::make()方法构造button，然后通过connectToolDefinitionUseKey()
        // 做一次连接，一遍button--buttoncontrol--command联系在一起

        /// \brief 向DropDownButton的下拉列表内添加PushButton
        /// \param pDropDown DropdownButton指针
        /// \param cmdId 添加的button对应的cmdid
        /// \return 成功返回新增的button指针，失败返回空指针nullptr
        static ButtonEx* addPushButtonToDropDown(DropDownButton* pDropDown, const std::wstring& cmdId, Module* pModule = nullptr /*actived*/);

        /// \brief 向DropDownButton的下拉列表的特定位置新插入一个PushButton
        /// \param pDropDown DropdownButton指针
        /// \param cmdId 新插入的button对应的cmdid
        /// \param buttonIndex  [in]button的索引，新插入的button的索引为buttonIndex
        /// \return 成功返回新插入的button指针，失败返回空指针nullptr
        static ButtonEx* insertPushButtonToDropDown(DropDownButton* pDropDown, const std::wstring& cmdId, int buttonIndex, Module* pModule = nullptr /*actived*/);
    };
}
